home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * NNTP Server/Client - See RFC977
- * Jeffrey R. Comstock. - NR0D - Bloomington, Minnesota USA
- * Copyright 1990 Jeffrey R. Comstock, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- *
- * DB3FL 9107xx: heavily rewritten and bug fixing in file-handling
- *
- * ported to NOS by PE1NMB - 920120
- *
- * Mods by PA0GRI and WG7J
- */
-
- #include <stdio.h>
- #include <time.h>
- #include <stdarg.h>
- #include <ctype.h>
- #include <setjmp.h>
- #include <errno.h>
- #if !defined(OS2)
- #include <dos.h>
- #include <dir.h>
- #include <io.h>
- #endif
- #include <sys\stat.h>
- #include <string.h>
- #include "global.h"
- #include "config.h"
- #ifdef NNTPS
- #include "mbuf.h"
- #include "cmdparse.h"
- #include "socket.h"
- #include "iface.h"
- #include "proc.h"
- #include "smtp.h"
- #include "commands.h"
- #include "dirutil.h"
- #include "ftp.h"
- #include "netuser.h"
- #include "nntp.h"
- #include "session.h"
- #include "files.h"
- #include "smtp.h"
- #include "bm.h"
- #ifdef LESS_WHINING
- #include "pc.h"
- #include "usock.h"
- #include "nr4.h"
- #include "netrom.h"
- #include "udp.h"
- #include "tcp.h"
- #include "ip.h"
- #endif
-
- int setintrc __ARGS((int16 *var,char *label,int argc, char *argv[],int minval,int16 maxval));
- FILE *open_file __ARGS((char *name,char *mode,int s,int t));
- FILE *temp_file __ARGS((int s,int t)); /* NMB */
-
- /***************************************************************************/
-
-
- #undef CONTROL /* reverse NNTP function (not implemented yet) */
- #define LINE 80
-
- static int Snntp = -1; /* prototype socket for service */
- static int16 Nntpquiet = 0;
- int Filecheck = 0; /* flag if file system has been checked */
-
- struct post *Post = NULLPOST;
- struct Servers *Nntpserver = NULLSERVER;
-
- static char *Host = NULLCHAR;
- static char NEol[] = ".\n";
-
- /*############################ NNTP COMMANDS #################################*/
-
- /* Command table */
- static char *commands[] = {
- "quit",
- #define QUIT_CMD 0
- "help",
- #define HELP_CMD 1
- "list",
- #define LIST_CMD 2
- "group",
- #define GROUP_CMD 3
- "debug",
- #define DEBUG_CMD 4
- "article",
- #define ARTICLE_CMD 5
- "next",
- #define NEXT_CMD 6
- "xinfo",
- #define XINFO_CMD 7
- "ihave",
- #define IHAVE_CMD 8
- "newnews",
- #define NEWNEWS_CMD 9
- "head",
- #define HEAD_CMD 10
- "body",
- #define BODY_CMD 11
- "stat",
- #define STAT_CMD 12
- "last",
- #define LAST_CMD 13
- "slave",
- #define SLAVE_CMD 14
- NULLCHAR
- };
-
- static char artmsg[] = " Article retrieved - ";
-
- static char info[] = "100 %s Info:\n";
- static char xinfo[] = "100 No info available\n";
- static char debug[] = "100 DEBUG %s\n";
-
- static char nnversion[] = "20%s %s NNTP version %s ready at %s\n";
- static char slave[] = "202 SLAVE %s\n";
- static char closing[] = "203 Closing\n";
- static char listarticle[]= "211 %u %u %u%s\n";
- static char retrieve[] = "220 %u%s%shead and body follow\n";
- static char head[] = "221 %u%s%sHead\n";
- static char body[] = "222 %u%s%sBody\n";
- static char statistics[]= "223 %u%s%sStatistics\n";
- static char sepcmd[] = "223 %u%s%srequest text separately\n";
- static char newnews_t[] = "230 New news by message id follows\n";
- static char transok[] = "235 Thanks\n";
-
- static char sendart[] = "335 Send article, end with .\n";
-
- static char nogroup[] = "411 No such newsgroup\n";
- static char noselect[] = "412 No newsgroup selected\n";
- static char nonext[] = "421 No next article\n";
- static char noprev[] = "422 No previous article\n";
- static char noart[] = "430 No such article\n";
- static char notwanted[] = "435 Article not wanted - do not send it\n";
- static char transnotok[]= "437 Article rejected - header garbled - do not try again\n";
-
- static char badsyntax[] = "501 Syntax error\n";
- static char error[] = "503 Command not performed\n";
- static char nospace[] = "503 Not enough disk space left\n";
- static char lowmem[] = "503 System overloaded\n";
- static char fatal[] = "503 Fatal error FILE %s\n";
-
- static char quitcmd[] = "QUIT\n";
- static char help[] = "NNTP Server 1992,\n\n"
- "100 ARTICLE BODY GROUP HEAD HELP IHAVE\n"
- "100 LAST LIST NEWNEWS NEXT QUIT STAT\n";
-
- static void
- rip2(register char *s)
- {
- register char *cp;
-
- if((cp = strpbrk(s,"\r\n")) != NULLCHAR)
- *cp = '\0';
- }
-
- /* main directory-creating routine
- * handles special chars in pathname - especially for MSDOS
- * returncode: -1 error; 0 success
- */
- static int
- make_dir(path,s)
- char *path;
- int s;
- {
- register char *cp;
-
- if(path == NULLCHAR)
- return -1;
- #ifdef MSDOS
- while((cp = strchr(path,'\\')) != NULLCHAR)
- *cp = '/';
- #endif
- if (access(path,0)) {
- if (mkdir(path)) {
- tprintf("Can't create %s: %s\n",path,strerror(errno));
- if(s)
- usprintf(s,fatal,path);
- return -1;
- }
- }
- return 0;
- }
-
- /* main message-opening routine
- * returncode: NULLFILE if error; filepointer success */
- static FILE *
- open_message(mp,f)
- struct nntpsv *mp;
- FILE *f;
- {
- char line[LineLen];
-
- /* mp already checked */
-
- if(f != NULLFILE)
- fclose(f);
-
- sprintf(line,"%s/%u",mp->path,mp->pointer);
-
- if ((f = open_file(line,READ_TEXT,0,0)) == NULLFILE)
- usputs(mp->s,noart);
- return f;
- }
-
- /* file-receiving routine
- * returncode: -1 if error or 'recvline' faults; 0 success; 1 if blank line */
- static int
- recv_file(fp,s)
- FILE *fp;
- int s;
- {
- char line[LineLen];
- int check = 0;
-
- for (;;) {
- if (recvline(s,line,LineLen) == -1)
- return -1;
- rip2(line);
- if (strcmp(line,".") == 0) {
- return 0;
- }
- if(!check) { /* only enabled on first line! */
- check = 1;
- if (*line == '\0') /* check for blank line */
- return 1;
- }
- fprintf(fp,"%s\n",line);
- }
- }
-
- /* checks incoming article-id against existing articles
- * returncode: -1 if error; 1 if article exists; 0 no article found */
- static int
- check_article(id)
- char *id;
- {
- char *p, line[LineLen];
- FILE *f;
-
- if(id == NULLCHAR || (p = strchr(id,'<')) == NULLCHAR
- || (f = open_file(History,READ_TEXT,0,1)) == NULLFILE)
- return -1;
-
- for(;;) {
- if (fgets(line,LineLen,f) == NULL) {
- fclose(f);
- return 0;
- }
- if (strstr(line,p) != NULL) {
- fclose(f);
- return 1;
- }
- }
- }
-
- /* checks for not valid chars in a line
- * returncode: 0 if valid; 1 if invalid */
- static int
- check_blank(bp)
- char *bp;
- {
- if (strpbrk(bp,"!@#$%^&*()_+=<>,./?~`[]{}\|0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") == NULL)
- return 1;
- return 0;
- }
-
- /* main file-checking routine
- * returncode: -1 if error; 0 success */
- static int
- check_file(char *path)
- {
- FILE *hFile;
- if(path == NULLCHAR)
- return -1;
- if(access(path,0)) {
- hFile = fopen(path, "W");
- if (hFile)
- fclose(hFIle);
- }
- return 0;
- }
-
- /* checks if two spaces exists in given string
- * returncode: -1 if error; 1 success */
- static int
- check_one(char *str)
- {
- register char *cp;
-
- if(str == NULLCHAR || (cp = strchr(str,' ')) == NULLCHAR)
- return -1;
- cp++;
-
- if (strchr(cp,' ') == NULLCHAR)
- return -1;
-
- return 1;
- }
-
- /* checks the file-system used for NNTP
- * returncode: -1 if error; 0 success - and "Filecheck" is set to 1 */
- static int
- check_system(void)
- {
- FILE *f;
- char line[LineLen];
- int error = 0;
-
- if (Post == NULLPOST)
- donnprofile(10,NULL,NULL);
-
- if(Filecheck)
- return 0;
-
- error = make_dir(Forward,0);
- error |= check_file(Pointer);
- error |= check_file(History);
- error |= check_file(Active);
- error |= check_file(Poll);
-
- if(error)
- goto quit;
-
- sprintf(line,"%s/fwd.seq",Newsdir);
- if (access(line,0)) {
- if((f = open_file(line,"w+",0,1)) == NULLFILE) {
- goto quit;
- }
- fputs("1\n",f);
- fclose(f);
- }
- sprintf(line,"%s/sequence.seq",Mailqdir);
- if (access(line,0)) {
- if((f = open_file(line,"w+",0,1)) == NULLFILE) {
- goto quit;
- }
- fputs("1\n",f);
- fclose(f);
- }
- Filecheck = 1;
- return 0;
-
- quit:
- Filecheck = 0;
- tputs("Error in NNTP file system\n");
- return -1;
- }
-
- /* handles the response code of an incoming msg
- * returncode: -1 error; 0 no code; value of response code on success */
- static int
- getreply(cb)
- struct nntpsv *cb;
- {
- int response;
-
- while(recvline(cb->s,cb->buf,LineLen) != -1) {
- /* skip informative messages and blank lines */
- if(cb->buf[0] == '\0' || cb->buf[0] == '1')
- continue;
- sscanf(cb->buf,"%d",&response);
- return (response < 500) ? response : -1;
- }
- return -1;
- }
-
- /* returncode: -1 error; 1 success; 0 no entry */
- static int
- get_path(group,mp)
- char *group;
- struct nntpsv *mp;
- {
- FILE *f;
- char line[LineLen], *cp;
-
- if(group == NULLCHAR || mp == NULLNNTPSV
- || (f = open_file(Pointer,READ_TEXT,mp->s,0)) == NULLFILE)
- return -1;
-
- group++;
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- if (strcspn(line," ") != strlen(group))
- continue;
- if (strnicmp(group,line,strlen(group)) == 0) {
- cp = (strchr(line,' ')) + 1;
- if (mp->path != NULLCHAR)
- free(mp->path);
- mp->path = strdup(cp);
- rip2(mp->path);
- fclose(f);
- return 1;
- }
- }
- fclose(f);
- return 0;
- }
-
- /* checkes if path to given article exists
- * returncode: -1 error; 1 success; 0 no path */
- static int
- get_path2(art)
- struct article *art;
- {
- FILE *f;
- char line[LineLen], *p;
-
- if(art->group == NULLCHAR
- || (f = open_file(Pointer,READ_TEXT,0,1)) == NULLFILE)
- return -1;
-
- p = art->group;
- art->path = NULLCHAR;
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- if (strcspn(line," ") != strlen(p))
- continue;
- if (strnicmp(p,line,strlen(p)) == 0) {
- p = (strchr(line,' ')) + 1;
- if(art->path != NULLCHAR)
- free(art->path);
- art->path = strdup(p);
- rip2(art->path);
- fclose(f);
- return 1;
- }
- }
- fclose(f);
- return 0;
- }
-
- /* returncode: -1 if error; 1 success; 0 no pointer */
- static int
- get_pointer(group,mp)
- char *group;
- struct nntpsv *mp;
- {
- FILE *f;
- char line[LineLen], *p;
-
- if(group == NULLCHAR || mp == NULLNNTPSV
- || (f = open_file(Active,READ_TEXT,mp->s,0)) == NULLFILE)
- return -1;
-
- group++;
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- if (strcspn(line," ") != strlen(group))
- continue;
- if (strnicmp(group,line,strlen(group))==0) {
- p = strchr(line,' ');
- mp->last = (unsigned)atoi(p);
- p++;
- mp->first = (unsigned)atoi(strchr(p,' '));
- mp->pointer = (mp->first > mp->last ) ? 0 : mp->first;
- fclose(f);
- return 1;
- }
- }
- fclose(f);
- return 0;
- }
-
- /* creating path to a new newsgroup
- * handling of "." and "\" in pathnames especially MSDOS */
- /* returncode: -1 error; 0 success */
- static int
- make_path(group)
- char *group;
- {
- FILE *f;
- char cp[LineLen], cp1[LineLen], *cp2;
- int got_it;
-
- if (group == NULLCHAR
- || (f = open_file(Pointer,APPEND_TEXT,0,1)) == NULLFILE)
- return -1;
-
- got_it = 0;
- strcpy(cp1,group);
-
- for(;;) {
- if((cp2 = strchr(cp1,'.')) != NULLCHAR)
- *cp2 = '\0';
- else
- got_it = 1;
-
- sprintf(cp,"%s/%s",Newsdir,cp1);
-
- if(make_dir(cp,0)) {
- fclose(f);
- return -1;
- }
- if(got_it) {
- fprintf(f,"%s %s\n",group,cp);
- fclose(f);
- return 0;
- }
- *cp2 = '/';
- }
- }
-
- static int
- update_list(a)
- struct nntpsv *a;
- {
- FILE *f, *t;
- char *p, *p1, l2[LineLen];
-
- if((f = open_file(Active,READ_TEXT,a->s,0)) == NULLFILE)
- return -1;
-
- if ((t = temp_file(0,1)) == NULLFILE) {
- fclose(f);
- return -1;
- }
- p1 = a->ap->group;
- a->ap->number = 0;
- for (;;) {
- if (fgets(a->buf,LineLen,f) == NULL)
- break;
- a->ap->tmpu = strcspn(a->buf," ");
- strncpy(l2,a->buf,a->ap->tmpu);
- l2[a->ap->tmpu] = '\0';
- if (strcmp(p1,l2) == 0) {
- p = strchr(a->buf,' ') + 1;
- a->ap->number = (unsigned)atoi(p);
- (a->ap->number)++;
- p = strchr(p,' ');
- fprintf(t,"%s %5.5u%s",p1,a->ap->number,p);
- } else
- fputs(a->buf,t);
- }
- fclose(f);
- rewind(t);
- if ((f = open_file(Active,WRITE_TEXT,a->s,0)) == NULLFILE) {
- fclose(t);
- return -1;
- }
- for(;;) {
- if (fgets(a->buf,LineLen,t) == NULL)
- break;
- fputs(a->buf,f);
- }
- fclose(t);
- if (a->ap->number == 0) {
- make_path(a->ap->group);
- a->ap->number = 1;
- fprintf(f,"%s 00001 00001 y\n",a->ap->group);
- }
- fclose(f);
- return (a->ap->number);
- }
-
- /* returncode: -1 error; 0 success */
- static int
- dup_f(in,out,mp)
- FILE *in;
- FILE *out;
- struct nntpsv *mp;
- /* Path: bug in col 1 of article body bug fixed by G4JEC 901019....*/
- {
- char *p;
- int blank_line_flag = 1;
-
- for(;;) {
- if (fgets(mp->buf,LineLen,in) == NULL)
- return 0;
-
- if (blank_line_flag)
- if (strnicmp(mp->buf,Hdrs[PATH],5) == 0) {
- p = strchr(mp->buf,' ') + 1;
- fprintf(out,"%s%s!%s",Hdrs[PATH],Host,p);
- continue;
- }
- /* oh oh - nntpserv is modifying articles....*/
- if (strlen(mp->buf) == 1 && mp->buf[0] == '.')
- continue;
- fputs(mp->buf,out);
- if(!check_blank(mp->buf))
- blank_line_flag = 0;
- }
- }
-
- /* returncode: < 1 if error; 1 success */
- static int
- dofwd(mp,f,history)
- struct nntpsv *mp;
- FILE *f;
- FILE *history;
- {
- FILE *fwd;
-
- if(mp == NULLNNTPSV)
- return -1;
-
- sprintf(mp->buf,"%s/fwd.seq",Newsdir);
- if ((fwd = open_file(mp->buf,"r+",mp->s,0)) == NULLFILE)
- return -1;
-
- fgets(mp->buf,LineLen,fwd);
- mp->hold_i = atoi(mp->buf) + 1;
- fprintf(history," JUNK/%u",mp->hold_i);
- rewind(fwd);
- fprintf(fwd,"%u",mp->hold_i);
- fclose(fwd);
-
- sprintf(mp->buf,"%s/%u",Forward,mp->hold_i);
- if ((fwd = open_file(mp->buf,WRITE_TEXT,mp->s,0)) == NULLFILE)
- return -2;
-
- rewind(f);
- dup_f(f,fwd,mp);
- fclose(fwd);
- return 1;
- }
-
- #ifdef CONTROL
- static int
- docontrol(f,mp)
- FILE *f;
- struct nntpsv *mp;
- {
- struct head *h;
-
- if(f == NULLFILE || mp == NULLNNTPSV
- || (h = (struct head *)callocw(1,sizeof(struct head))) == NULLHEAD))
- return -1;
-
- rewind(f);
- h->subject = h->from = h->reply_to = h->id = NULLCHAR;
-
- for(;;) {
- if ((fgets(mp->buf,LineLen,f)) == NULL)
- break;
- if (check_blank(mp->buf))
- break;
- rip2(mp->buf);
- if (strncmp(mp->buf,Hdrs[SUBJECT],9) == 0)
- h->subject = strdup(mp->buf);
- if (strncmp(mp->buf,Hdrs[FROM],6) == 0)
- h->from = strdup(mp->buf);
- if (strnicmp(mp->buf,Hdrs[REPLYTO],10) == 0)
- h->reply_to = strdup(mp->buf);
- if (strnicmp(mp->buf,Hdrs[MSGID],12) == 0)
- h->id = strdup(strchr(mp->buf,'<'));
- }
- if (h->subject != NULLCHAR)
- if (strncmp(h->subject,"Subject: sendme ",16) == 0)
- dosendme(h);
- if (h->subject != NULLCHAR)
- free(h->subject);
- if (h->from != NULLCHAR)
- free(h->from);
- if (h->reply_to != NULLCHAR)
- free(h->reply_to);
- if (h->id != NULLCHAR)
- free(h->id);
- free((char *)h);
- return 0;
- }
- #endif
-
- static int
- xfer_article2(f,mp)
- FILE *f;
- struct nntpsv *mp;
- {
- char line[LineLen], *p, *group = NULLCHAR, *p1, *from = NULLCHAR;
- FILE *fptr, *history;
- struct tm *stm;
- int x;
- #ifdef CONTROL
- int control = 0;
- #endif
- long currtime;
-
- if(f == NULLFILE || mp == NULLNNTPSV ||
- (history = open_file(History,APPEND_TEXT,mp->s,0)) == NULLFILE)
- return -1;
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- rip2(line);
- if (strnicmp(line,Hdrs[FROM],6) == 0) {
- p = strchr(line,' ') + 1;
- from = strdup(p);
- continue;
- }
- if (strnicmp(line,Hdrs[NEWSGROUPS],12) == 0) {
- p = strchr(line,' ') + 1;
- group = strdup(p);
- break;
- }
- }
- time(&currtime);
- stm = localtime(&currtime);
- fprintf(history,"%s %2.2d%2.2d%2.2d %2.2d%2.2d%2.2d",
- mp->id,
- stm->tm_year,stm->tm_mon+1,stm->tm_mday,
- stm->tm_hour,stm->tm_min,stm->tm_sec);
-
- mp->hold_i = 0;
- p = group;
- if((mp->ap = (struct article *)callocw(1,sizeof(struct article))) == NULLARTICLE)
- goto quit;
- x = 1;
- while (x) {
- if ((p1 = strchr(p,',')) != NULLCHAR) {
- p1 = line;
- while (*p != ',')
- *(p1++)=*(p++);
- *p1 = '\0';
- p++;
- mp->ap->group = strdup(line);
- } else {
- mp->ap->group = strdup(p);
- x = 0;
- }
- update_list(mp);
- if (mp->ap->number > 0) {
- get_path2(mp->ap);
- mp->hold_i = 1;
- sprintf(line,"%s/%u",mp->ap->path,mp->ap->number);
- rewind(f);
- if ((fptr = open_file(line,WRITE_TEXT,mp->s,0)) == NULLFILE) {
- fclose(history);
- free(mp->ap->group);
- goto quit;
- }
- dup_f(f,fptr,mp);
- fclose(fptr);
- fprintf(history," %s/%d",mp->ap->group,mp->ap->number);
- #ifdef CONTROL
- if (strcmp(mp->ap->group,"control") == 0)
- control = 1;
- #endif
- free(mp->ap->path);
- }
- free(mp->ap->group);
- }
- if (mp->hold_i == 0) {
- if ((x = dofwd(mp,f,history)) < 1)
- mp->hold_i = 0;
- }
- fputc('\n',history);
- fclose(history);
- time(&currtime);
- if(Nntpquiet < 2)
- tprintf("New mail in newsgroup %s\n from <%s> at %s%s",
- group,from,ctime(&currtime),
- (Nntpquiet < 1) ? "\007" : "");
-
- #ifdef CONTROL
- if (control == 1)
- docontrol(f,mp);
- #endif
- quit:
- free(from);
- free(group);
- free((char *)mp->ap);
- return 1;
- }
-
- static void
- nntppoll(unused,cb1,p)
- int unused;
- void *cb1;
- void *p;
- {
- char *cp, line[LineLen];
- struct sockaddr_in fsocket;
- struct nntpsv *cb;
- struct tm *stm, *ltm;
- FILE *f, *f1, *pf;
- long t;
- int r, now;
- struct Servers *sp = (struct Servers *) cb1;
- long currtime;
-
- if (!run_timer(&sp->nntpt)) /* if timer had stopped there is an
- return; * active session */
-
- if (!Filecheck)
- if(check_system())
- return;
-
- if(availmem() < Memthresh) {
- start_timer(&sp->nntpt);
- return;
- }
-
- /* check connection window */
- time(&currtime);
- ltm = localtime(&currtime);
- now = ltm->tm_hour * 100 + ltm->tm_min;
- if (sp->lowtime < sp->hightime) {
- /* doesn't cross midnight */
- if (now < sp->lowtime || now >= sp->hightime) {
- start_timer(&sp->nntpt);
- return;
- }
- } else {
- if (now < sp->lowtime && now >= sp->hightime) {
- start_timer(&sp->nntpt);
- return;
- }
- }
- if((pf = open_file(Poll,"r+",0,1)) == NULLFILE ||
- (cb = (struct nntpsv *)callocw(1,sizeof(struct nntpsv))) == NULLNNTPSV) {
- start_timer(&sp->nntpt);
- return;
- }
- stop_timer(&sp->nntpt);
-
- cb->fname = NULLCHAR;
- cb->newnews = NULLCHAR;
- rewind(pf);
-
- for(t = 0L; fgets(line,LineLen,pf) != NULLCHAR; t = ftell(pf)) {
- if((cp = strchr(line,' ')) == NULLCHAR)
- continue; /* something wrong with this line, skip it */
- *cp = '\0';
- if(strnicmp(line,sp->name,strcspn(line," ")-1) == 0) {
- rip2(cp+1);
- cb->newnews = strdup(cp+1);
- /* Prepare to write back the current host and date */
- fseek(pf,t,0);
- break;
- }
- }
-
- if(cb->newnews == NULLCHAR)
- cb->newnews = strdup("800101 000000");
-
- fsocket.sin_family = AF_INET;
- fsocket.sin_addr.s_addr = cb->dest = sp->dest;
- fsocket.sin_port = IPPORT_NNTP;
-
- if((cb->s = socket(AF_INET,SOCK_STREAM,0)) == -1)
- goto quit;
- sockmode(cb->s,SOCK_ASCII);
-
- if(connect(cb->s,(char *)&fsocket,SOCKSIZE) == -1)
- goto quit;
- log(cb->s,"Connect NNTP");
-
- time(&currtime);
- stm = localtime(&currtime);
-
- if(getreply(cb) == -1) /* throw away any hello msg */
- goto quit;
-
- #ifdef XXX
- usputs(cb->s,"SLAVE\n");
- if(getreply(cb) != 202)
- goto quit;
- #endif
- cb->slave = 1;
-
- if ((f = temp_file(0,1)) == NULLFILE)
- goto quit;
-
- usprintf(cb->s,"NEWNEWS %s %s\n",sp->newsgroups,cb->newnews);
- if(getreply(cb) != 230) {
- fclose(f);
- goto quit;
- }
- if(recv_file(f,cb->s) == -1) {
- usprintf(cb->s,quitcmd);
- fclose(f);
- goto quit;
- }
- if ((f1 = temp_file(cb->s,1)) == NULLFILE) {
- fclose(f);
- goto quit;
- }
- rewind(f);
-
- for(;;) {
- if (fgets(cb->buf,LineLen,f) == NULL)
- break;
- rip2(cb->buf);
- if (strcmp(cb->buf,".") == 0)
- break;
- if (check_article(cb->buf) == 1)
- continue;
- usprintf(cb->s,"ARTICLE %s\n",cb->buf);
- for (;;) {
- if ((r = recvline(cb->s,cb->buf,LineLen)) == -1)
- break;
- rip2(cb->buf);
- if(!isdigit(cb->buf[0])) {
- r = -1;
- continue;
- } else {
- r = atoi(cb->buf);
- break;
- }
- }
- if(r == -1)
- break;
- if (r == 220) {
- recv_file(f1,cb->s);
- rewind(f1);
- for ( ;; ) {
- if (fgets(cb->buf,LineLen,f1) == NULL)
- break;
- rip2(cb->buf);
- if (strnicmp(cb->buf,Hdrs[MSGID],12) == 0) {
- cb->id = strdup((strchr(cb->buf,' ')) + 1);
- break;
- }
- }
- rewind(f1);
- xfer_article2(f1,cb);
- free(cb->id);
- }
- fclose(f1);
- if ((f1 = temp_file(cb->s,1)) == NULLFILE)
- goto quit;
- }
- fclose(f);
- fclose(f1);
- usprintf(cb->s,quitcmd);
- if (recvline(cb->s,cb->buf,LineLen) == -1)
- goto quit;
- quit:
- if(errno == 0) {
- /* Now write back the opening date and time */
- fprintf(pf,"%s %02d%02d%02d %02d%02d%02d\n",
- sp->name,
- stm->tm_year,
- stm->tm_mon + 1,
- stm->tm_mday,
- stm->tm_hour,
- stm->tm_min,
- stm->tm_sec);
- }
- fclose(pf);
-
- close_s(cb->s);
- free(cb->newnews);
- free((char *)cb);
- start_timer(&sp->nntpt);
- }
-
- static int
- ngmatcha(func,dflt,ngspec,matchlist)
- int (*func)();
- int dflt;
- struct g_list *ngspec;
- struct g_list *matchlist;
- {
- register int match;
- char *cp;
- struct g_list *m,*n;
-
- match = dflt;
- m = matchlist;
- for(;;) {
- if ((cp = strchr(m->str,'/')) != NULLCHAR)
- *cp = '\0';
- n = ngspec;
- for (;;) {
- if (n->str[0] == '!') { /* Handle negation */
- if ((*func)(n->str+1, m->str)) {
- match = 0;
- }
- } else {
- if ((*func)(n->str, m->str)) {
- match = 1;
- }
- }
- if (n->next == NULLG)
- break;
- else
- n=n->next;
- }
- if (m->next == NULLG)
- break;
- else
- m=m->next;
- }
- return (match);
- }
-
- static int
- restreql(w, s)
- register char *w;
- register char *s;
- {
- while (*s && *w) {
- switch (*w) {
- case '*':
- for (w++; *s; s++)
- if (restreql(w, s))
- return 1;
- break;
- default:
- if (*w != *s)
- return 0;
- w++, s++;
- break;
- }
- }
- if (*s)
- return 0;
- while (*w)
- if (*w++ != '*')
- return 0;
-
- return 1;
- }
-
- /* converts timestring to unix-compatible structure
- * returncode: 0 (!!) if error; > 0 success */
- static int32
- make_nntime(d,t,str)
- struct date *d;
- struct time *t;
- char *str;
- {
- register char *cp;
- char tmp[3];
-
- if(str == NULLCHAR)
- return 0;
-
- tmp[2] = '\0';
- cp = str;
-
- strncpy(tmp,cp,2);
-
- d->tm_year = atoi(tmp)+1900;
-
- if (d->tm_year < 1980)
- d->tm_year = 1980;
-
- if (d->tm_year > 2099)
- goto quit;
-
- cp+=2;
-
- strncpy(tmp,cp,2);
- d->tm_mon = atoi(tmp);
- if (d->tm_mon < 1 || d->tm_mon > 12)
- goto quit;
-
- cp+=2;
-
- strncpy(tmp,cp,2);
- d->tm_day = atoi(tmp);
- if (d->tm_day < 1 || d->tm_day > 32)
- goto quit;
-
- cp+=3;
-
- strncpy(tmp,cp,2);
- t->tm_hour = atoi(tmp);
- if (t->tm_hour < 0 || t->tm_hour > 24)
- goto quit;
-
- cp+=2;
-
- strncpy(tmp,cp,2);
- t->tm_min = atoi(tmp);
- if (t->tm_min < 0 || t->tm_min > 60)
- goto quit;
-
- cp+=2;
-
- strncpy(tmp,cp,2);
- t->tm_sec = atoi(tmp);
- if (t->tm_sec < 0 || t->tm_sec > 60)
- goto quit;
-
- return (dostounix(d,t));
- quit :
- return 0L;
- }
-
- /* returncode: -1 if error; 0 if no new news; 1 new news available */
- static int
- newnews(string,mp,f)
- char *string;
- struct nntpsv *mp;
- FILE *f;
- {
- register int i,j;
- char *cp, *cp1, line[LineLen], groups[LineLen];
- struct g_list *ng, *hist, *ngp, *histp, *ptr;
- FILE *f1;
- int all = 1;
-
- if (check_one(string) == -1)
- return -1;
-
- cp = string;
- i = 1;
-
- while (*(cp++) > 32)
- i++;
- if (strlen(cp) < 13)
- return -1;
-
- strncpy(groups,string,i-1);
- groups[i-1] = '\0';
- if(strcmp(groups,"*") != 0)
- all = 0;
-
- mp->datest = (struct tm *)callocw(1,sizeof(struct tm));
- mp->timest = (struct tm *)callocw(1,sizeof(struct tm));
-
- gettime(mp->timest);
- getdate(mp->datest);
-
- if ((mp->unixtime = make_nntime(mp->datest,mp->timest,cp)) == 0)
- goto quit;
- if (mp->unixtime == -1L)
- return 0;
-
- if (!all) {
- ng = ngp = (struct g_list *)callocw(1,(sizeof(struct g_list)));
- cp = groups;
-
- for (;;) {
- if ((cp1 = strchr(cp,',')) == NULLCHAR ) {
- ng->str = strdup(cp);
- ng->next = NULLG;
- break;
- }
- j = strcspn(cp,",");
- ng->str = (char *)callocw(1,j+1);
- strncpy(ng->str,cp,j);
- ng->str[j] = '\0';
- ng->next = (struct g_list *)callocw(1,sizeof(struct g_list));
- ng = ng->next;
- cp1 = strchr(cp,',');
- if (cp1 != NULLCHAR)
- cp = cp1 + 1;
- else
- break;
- }
- }
-
- if ((f1 = open_file(History,READ_TEXT,mp->s,0)) == NULLFILE)
- goto quit;
-
- for (;;) {
- if (fgets(line,LineLen,f1) == NULL)
- break;
- rip2(line);
-
- if (!all) {
- for(i = 3, cp = line; i; --i)
- cp = strchr(cp,' ') + 1;
- histp = (struct g_list *)callocw(1,sizeof(struct g_list));
- hist = histp;
-
- for (;;) {
- if ((cp1 = strchr(cp,' ')) == NULLCHAR) {
- hist->str = strdup(cp);
- hist->next = NULLG;
- break;
- }
-
- j = strcspn(cp," ");
- hist->str = (char *)callocw(1,j+1);
- strncpy(hist->str,cp,j);
- hist->str[j] = '\0';
- hist->next = (struct g_list *)callocw(1,sizeof(struct g_list));
- hist = hist->next;
- cp1 = strchr(cp,' ');
- if (cp1 != NULLCHAR)
- cp = cp1 + 1;
- else
- break;
- }
- if (!ngmatcha(restreql,0,ngp,histp)) {
- ptr = histp;
- for (;;) {
- ptr = histp->next;
- free(histp->str);
- free(histp);
- histp = ptr;
- if (histp == NULLG)
- break;
- }
- continue;
- }
- }
- cp = strchr(line,' ') + 1;
- if ((mp->ftime = make_nntime(mp->datest,mp->timest,cp)) == 0) {
- fclose(f1);
- goto quit;
- }
- if ((mp->ftime - mp->unixtime) > 0) {
- cp = line;
- while ( *cp > 32 )
- fputc(*(cp++),f);
- fputc('\n',f);
- }
- if (!all) {
- ptr = histp;
- for (;;) {
- ptr = histp->next;
- free(histp->str);
- free(histp);
- histp = ptr;
- if (histp == NULLG)
- break;
- }
- }
- }
- fclose(f1);
- if (!all) {
- ptr = ngp;
- for (;;) {
- ptr = ngp->next;
- free(ngp->str);
- free(ngp);
- ngp = ptr;
- if (ngp == NULLG)
- break;
- }
- }
- free(mp->datest);
- free(mp->timest);
- return 1;
- quit:
- return 0;
- }
-
- /* handles incoming newnews-cmd
- * returncode: -1 if error; 0 no groups or bad syntax; 1 success */
- static int
- donewnews(string,mp)
- char *string;
- struct nntpsv *mp;
- {
- FILE *f;
- int ret;
-
- if((f = temp_file(mp->s,1)) == NULLFILE)
- return -1;
-
- ret = newnews(string,mp,f);
-
- switch(ret) {
- case -1: /* error in "newnews" routine */
- ret = 0;
- usputs(mp->s,badsyntax);
- break;
- case 0: /* no new news */
- usputs(mp->s,newnews_t);
- usputs(mp->s,NEol);
- break;
- default: /* new news available, send news file */
- rewind(f);
- usputs(mp->s,newnews_t);
- sendfile(f,mp->s,ASCII_TYPE,0);
- usputs(mp->s,NEol);
- ret = 1;
- break;
- }
- fclose(f);
- return ret;
- }
-
- /* change current newsgroup
- * returncode: -1 if error; 0 success; 1 no newsgroup */
- static int
- dogroup(mp,buf)
- struct nntpsv *mp;
- char *buf;
- {
- char *p;
- int er;
-
- if((p = strchr(buf,' ')) == NULLCHAR)
- return -1;
-
- er = get_path(p,mp);
-
- switch (er) {
- case 0:
- usputs(mp->s,nogroup);
- return 1;
- default:
- p = strchr(buf,' ');
- if (get_pointer(p,mp) == 1) {
- usprintf(mp->s,listarticle,
- mp->last - mp->first + 1,mp->first,mp->last,strchr(buf,' '));
- return 0;
- }
- case -1:
- usputs(mp->s,error);
- return -1;
- }
- }
-
-
- /* checks if newsgroup is selected
- * returncode: -1 no group selected; 0 success */
- static int
- check_grp(mp)
- struct nntpsv *mp;
- {
- if(mp == NULLNNTPSV || mp->path == NULLCHAR) {
- usputs(mp->s,noselect);
- return -1;
- }
- return 0;
- }
-
- /* get id-number of message
- * returncode: -1 if error; 0 if no message; 1 success */
- static int
- get_id(bp,mp)
- char *bp;
- struct nntpsv *mp;
- {
- FILE *f;
- char tmp[LineLen];
-
- if ((f = open_message(mp,NULLFILE)) == NULLFILE)
- return 0;
-
- for (;;) {
- if (fgets(tmp,LineLen,f) == NULL)
- break;
- if (check_blank(tmp))
- break;
- if (strnicmp(tmp,Hdrs[MSGID],12)==0) {
- fclose(f);
- strcpy(bp,strchr(tmp,' '));
- rip2(bp);
- return 1;
- }
- }
- fclose(f);
- strcpy(bp,"\0");
- return 0;
- }
-
- /* gets next news of newsgroup
- * returncode: -1 if error; 0 no news; 1 success */
- static int
- get_next(mp)
- struct nntpsv *mp;
- {
- FILE *f;
-
- for (;;) {
- if (mp->pointer == 0 ) {
- usputs(mp->s,nonext);
- return 0;
- }
- if (++(mp->pointer) > mp->last) {
- mp->pointer--;
- usputs(mp->s,nonext);
- return 0;
- }
- sprintf(mp->buf,"%s/%u",mp->path,mp->pointer);
- if ((f = open_file(mp->buf,READ_TEXT,mp->s,0)) != NULLFILE) {
- fclose(f);
- return 1;
- }
- }
- }
-
- /* gets last news of newsgroup
- * returncode: -1 if error; 0 no news; 1 success */
- static int
- get_last(mp)
- struct nntpsv *mp;
- {
- FILE *f;
-
- for (;;) {
- if (mp->pointer == 0) {
- usputs(mp->s,noprev);
- return 0;
- }
- if (--(mp->pointer) < mp->first) {
- mp->pointer++;
- usputs(mp->s,noprev);
- return 0;
- }
- sprintf(mp->buf,"%s/%u",mp->path,mp->pointer);
- if ((f = open_file(mp->buf,READ_TEXT,mp->s,0)) != NULLFILE) {
- fclose(f);
- return 1;
- }
- }
- }
-
- static int
- art_ret(mp)
- struct nntpsv *mp;
- {
- if(get_id(mp->buf,mp) == -1)
- return -1;
- return usprintf(mp->s,retrieve,mp->pointer,mp->buf,artmsg);
- }
-
- static int
- doarticle(buf,mp) /* Sends article <message-id> to the client */
- char *buf;
- struct nntpsv *mp;
- {
- FILE *f;
- char *p, *p2, *holds, line[LineLen];
-
- if((p = strchr(buf,'<')) == NULLCHAR
- || (f = open_file(History,READ_TEXT,mp->s,0)) == NULLFILE)
- return 0;
-
- for(;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- if (strstr(line,p) != NULL) {
- fclose(f);
-
- p = (strchr(line,' ')) + 14; /* point to the first newsgroup */
- p2 = strchr(p,'/'); /* point to article number */
- mp->hold_i = mp->pointer; /* save current pointer */
- holds = strdup(mp->path); /* save path of current article */
- mp->pointer = atoi((p2 + 1)); /* get the article number */
-
- if (mp->path != NULLCHAR) {
- free(mp->path);
- mp->path='\0';
- }
-
- *p2 = '\0';
- rip2(p);
-
- if (strncmp(p+1,"JUNK",6) == 0) {
- sprintf(mp->buf,"%s",Forward);
- mp->path = strdup(mp->buf);
- } else
- get_path(p,mp);
-
- if ((f = open_message(mp,f)) == NULLFILE) {
- usputs(mp->s,error);
- return 0;
- }
- art_ret(mp);
- sendfile(f, mp->s, ASCII_TYPE,0);
- fclose(f);
- usputs(mp->s,NEol);
- free(mp->path);
- mp->path=strdup(holds);
- mp->pointer=mp->hold_i;
- free(holds);
- return 1;
- }
-
- }
- fclose(f);
- usputs(mp->s,noart);
- return 0;
- }
-
- /* checks for a minimum header
- * returncode: -1 if error; 0 complete; 1 not complete */
- static int
- garbled(f)
- FILE *f;
- {
- /*
- * The minimum requirement for an incoming article is that it must have
- * a newsgroups: line, a message-id: line, and a blank line. This is
- * pretty forgiving.
- */
- char line[LineLen];
- int ok = 0;
-
- rewind(f);
- for(;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- if (strnicmp(line,Hdrs[NEWSGROUPS],12) == 0)
- ok |= 1;
- if (strnicmp(line,Hdrs[MSGID],12) == 0)
- ok |= 2;
- if (ok == 3)
- break;
- if (check_blank(line))
- break;
- }
- rewind(f);
- return (ok == 3) ? 0 : 1;
- }
-
- /* returncode: -1 if error; 0 success */
- static int
- get_article2(mp, id)
- struct nntpsv *mp;
- char *id;
- {
- FILE *f;
- int ret = -1;
-
- if((f = temp_file(0,1)) == NULLFILE)
- return -1;
-
- mp->ap = (struct article *)callocw(1,sizeof(struct article));
- mp->id = strdup(id);
- usputs(mp->s,sendart);
-
- if(recv_file(f,mp->s) == -1)
- goto quit;
-
- if ((ret = garbled(f)) != 0) {
- usputs(mp->s,transnotok);
- goto quit;
- }
- if(xfer_article2(f,mp) == 0)
- goto quit;
- usputs(mp->s,transok);
-
- /* free_ap(mp); <------------ */
- quit:
- /* free((char *)mp->ap); <------------ */
- free(mp->id);
- fclose(f);
- return ret;
- }
-
- void
- poll(p)
- void *p;
- {
- newproc("NNTP Client", 2048, nntppoll, 0, p, NULL, 0);
- }
-
- static void
- nntpserv(s,unused,p)
- int s;
- void *unused;
- void *p;
- {
- struct nntpsv *mp;
- FILE *fp;
- long t;
- int cnt;
- char **cmdp, *arg, *cp, *cmd, buf[LineLen];
-
- sockmode(s,SOCK_ASCII);
- sockowner(s,Curproc); /* We own it now */
- log(s,"open NNTP");
-
- if (!Filecheck)
- if(check_system()) {
- usprintf(s,fatal,"STRUCTURE");
- log(s,"NNTP error - FILE STRU");
- close_s(s);
- return;
- }
- if((mp = (struct nntpsv *)callocw(1,sizeof(struct nntpsv))) == NULLNNTPSV) {
- usprintf(s,Nospace);
- close_s(s);
- return;
- }
- mp->s = s;
- mp->debug = 0;
- mp->path = NULLCHAR;
-
- time(&t);
- cp = ctime(&t);
- cp[24] = '\0';
-
- usprintf(s,nnversion,(Filecheck) ? "0" : "1",Host,Version,cp);
-
- loop:
- if ((cnt = recvline(s,buf,LineLen)) == -1) {
- /* He closed on us */
- goto quit;
- }
- rip2(buf);
- cmd = buf;
-
- /* Translate entire buffer to lower case */
- for(cp = cmd; *cp != '\0' ;cp++) {
- if ( *cp == ' ' ) break;
- *cp = tolower(*cp);
- }
- /* Find command in table; if not present, return syntax error */
- for(cmdp = commands; *cmdp != NULLCHAR; cmdp++)
- if(strnicmp(*cmdp,cmd,min(strlen(*cmdp),strlen(cmd))) == 0)
- break;
-
- if(*cmdp == NULLCHAR){
- usputs(mp->s,badsyntax);
- goto loop;
- }
- arg = &cmd[strlen(*cmdp)];
-
- /* Skip spaces after command */
- while(*arg == ' ')
- arg++;
-
- /* Execute specific command */
- switch(cmdp - commands) {
- case QUIT_CMD:
- goto quit;
- case NEWNEWS_CMD:
- if ((cp = strchr(buf,' ')) == NULLCHAR) {
- usputs(mp->s,badsyntax);
- break;
- }
- cp++;
- donewnews(cp,mp);
- break;
- case IHAVE_CMD:
- if ((cp = strchr(buf,'<')) == NULLCHAR) {
- usputs(mp->s,badsyntax);
- break;
- }
- if (check_article(cp) == 1) {
- usputs(mp->s,notwanted);
- break;
- }
- if(get_article2(mp,cp))
- goto quit;
- break;
- case HELP_CMD:
- usprintf(mp->s,"100 %s - help follows:\n",Host);
- if ((fp = open_file(Nhelp,READ_TEXT,0,0)) != NULLFILE ) {
- sendfile(fp,mp->s,ASCII_TYPE,0);
- fclose(fp);
- } else {
- usputs(mp->s,help);
- }
- usputs(mp->s,NEol);
- break;
- case XINFO_CMD:
- if ((fp = open_file(NInfo,READ_TEXT,0,0)) != NULLFILE ) {
- usprintf(mp->s,"100 %s - xinfo follows:\n",Host);
- sendfile(fp,mp->s,ASCII_TYPE,0);
- fclose(fp);
- } else {
- usputs(mp->s,xinfo);
- }
- usputs(mp->s,NEol);
- break;
- case LIST_CMD:
- if ((fp = open_file(Active,READ_TEXT,mp->s,0)) != NULLFILE) {
- sendfile(fp,mp->s,ASCII_TYPE,0);
- fclose(fp);
- usputs(mp->s,NEol);
- }
- break;
- case GROUP_CMD :
- dogroup(mp,&buf[0]);
- break;
- case HEAD_CMD : {
- if (check_grp(mp))
- break;
- if (get_id(mp->buf,mp) == 0)
- break;
- usprintf(mp->s,head,mp->pointer,mp->buf,artmsg);
- if ((fp = open_message(mp,fp)) == NULLFILE)
- break;
- for (;;) {
- if ((fgets(mp->buf,LineLen,fp)) == NULL)
- break;
- if (check_blank(mp->buf))
- break;
- usprintf(mp->s,"%s",mp->buf);
- }
- fclose(fp);
- usputs(mp->s,NEol);
- break;
- }
- case BODY_CMD : {
- if (check_grp(mp))
- break;
- if (get_id(mp->buf,mp) == 0)
- break;
- usprintf(mp->s,body,mp->pointer,mp->buf,artmsg);
- if ((fp = open_message(mp,fp)) == NULLFILE)
- break;
- mp->hold_i = 0;
- for (;;) {
- if ((fgets(mp->buf,LineLen,fp)) == NULL)
- break;
- if (mp->hold_i)
- usputs(mp->s,mp->buf);
- if (check_blank(mp->buf))
- mp->hold_i = 1;
- }
- fclose(fp);
- usputs(mp->s,NEol);
- break;
- }
- case STAT_CMD : {
- if (check_grp(mp))
- break;
- if (get_id(mp->buf,mp) == 0)
- break;
- usprintf(mp->s,statistics,mp->pointer,mp->buf,artmsg);
- break;
- }
- case ARTICLE_CMD : {
- if (strchr(buf,'<') != NULLCHAR) {
- doarticle(buf,mp);
- break;
- }
- if (check_grp(mp))
- break;
- cp = strchr(buf,'e');
- cp++;
- if ((cnt < 9 ) || (check_blank(cp))) {
- if ((fp = open_message(mp,fp)) == NULLFILE)
- break;
- art_ret(mp);
- sendfile(fp,mp->s,ASCII_TYPE,0);
- fclose(fp);
- usputs(mp->s,NEol);
- break;
- }
- if ((cp = strpbrk(buf,"0123456789")) != NULLCHAR) {
- cnt = atoi(cp);
- if ((cnt > mp->last) || ( cnt < mp->first)) {
- usputs(mp->s,noart);
- break;
- }
- mp->pointer = cnt;
- if ((fp = open_message(mp,fp)) == NULLFILE)
- break;
- art_ret(mp);
- sendfile(fp,mp->s,ASCII_TYPE,0);
- fclose(fp);
- usputs(mp->s,NEol);
- break;
- }
- break;
- }
- case NEXT_CMD : {
- if (check_grp(mp))
- break;
- if (get_next(mp) == 1) {
- if (get_id(buf,mp) == 1)
- usprintf(mp->s,sepcmd,mp->pointer,&buf[1],artmsg);
- break;
- }
- break;
- }
- case LAST_CMD :
- if (check_grp(mp))
- break;
- if (get_last(mp) == 1 ) {
- if (get_id(buf,mp) == 1)
- usprintf(mp->s,sepcmd,mp->pointer,&buf[1],artmsg);
- break;
- }
- break;
- /* This two following cmds currently are not used for much */
- case DEBUG_CMD:
- mp->debug = (mp->debug == 0) ? 1 : 0;
- usprintf(mp->s,debug,(mp->debug == 0) ? "OFF" : "ON");
- break;
- case SLAVE_CMD :
- mp->slave = (mp->slave == 0) ? 1 : 0;
- usprintf(mp->s,slave,(mp->slave == 0) ? "OFF" : "ON");
- break;
- }
- goto loop;
-
- quit:
- usputs(mp->s,closing);
- log(mp->s,"close NNTP");
- close_s(mp->s);
- if(mp->path != NULLCHAR)
- free(mp->path);
- if(mp->newnews != NULLCHAR)
- free(mp->newnews);
- if(mp->fname != NULLCHAR)
- free(mp->fname);
- if(mp->id != NULLCHAR);
- free(mp->id);
- free((char *)mp);
- }
-
- /* ---------------------------- NNTP-GATE --------------------------- */
-
- static char * near
- mkreplypath(FILE *data)
- {
- char buf[LINELEN], *cp, *cp1, *path;
-
- sprintf(buf,"%sNNTP_GATE@%s",Hdrs[PATH],Hostname);
- path = strdup(buf);
- rewind(data);
- while((fgets(buf,LINELEN,data)) != 0) {
- if(htype(buf) == DATE)
- break;
- if(htype(buf) == RECEIVED) {
- cp = strchr(buf,' ');
- cp++;
- cp = strchr(cp, ' ');
- cp++;
- cp1 = strpbrk(cp, ". \0");
- *cp1 = '\0';
- cp1 = mallocw(strlen(path)+strlen(cp)+2); /* */
- sprintf(cp1,"%s!%s",path,cp);
- free(path);
- path = cp1;
- }
- }
- return(path);
- }
-
- int
- nnGpost(FILE *data,char *from,struct list *le)
- {
- struct nntpsv *mp;
- char buf[LINELEN], *cp;
- FILE *f, *idf;
- int32 id;
- long currtime;
-
- if (!Filecheck)
- if(check_system())
- return -1;
-
- if ((f = temp_file(0,1)) == NULLFILE)
- return -1;
-
- mp = (struct nntpsv *)callocw(1,sizeof(struct nntpsv));
-
- /* build postuser */
- cp = mkreplypath(data);
- fprintf(f,"%s\n",cp);
- free((char *)cp);
- fprintf(f,"%s%s\n",Hdrs[FROM],from);
- /*----------------------------------------------------------------*
- * build newsgroup *
- *-----------------------------------------------------------------*/
- if((cp = strchr(le->val,'@')) != NULLCHAR)
- *cp = '\0';
- fprintf(f,"%s%s\n",Hdrs[NEWSGROUPS],&le->val[1]); /* skip the bang */
- /*----------------------------------------------------------------*
- * find the subject
- *-----------------------------------------------------------------*/
- rewind (data);
- while((fgets(buf,sizeof(buf),data))!=0) {
- if (htype(buf)== SUBJECT)
- break;
- continue;
- }
- fputs((*buf == 0) ? "Subject: (none)\n" : buf,f);
- /*-------------------------------------------------------------------*
- * use msgid of original message
- *--------------------------------------------------------------------*/
- rewind(data);
- while((fgets(buf,sizeof(buf),data))!=0) {
- if (htype(buf)== MSGID)
- break;
- continue;
- }
- if (*buf == 0) {
- sprintf(buf,"%s/sequence.seq",Mailqdir);
- idf = open_file(buf,"r+",0,1);
- id = atol(fgets(buf,LineLen,idf));
- rewind(idf);
- fprintf(idf,"%ld",id+2);
- fclose(idf);
- fprintf(f,"%s<%ld@%s>\n",Hdrs[MSGID],id,Hostname);
- sprintf(mp->buf,"<%ld@%s>",id,Hostname);
- } else {
- fputs(buf,f);
- rip(buf);
- cp = strchr(buf,'<');
- strcpy(mp->buf,cp);
- if (check_article(mp->buf))
- goto quit;
- }
- rewind (data);
- time(&currtime);
- fprintf(f,"Sender: NNTP@%s\n",Hostname);
- /*-------------------------------------------------------------------*
- * message follows *
- *--------------------------------------------------------------------*/
- fputs("Comments: Message transferred from SMTP\n",f);
- while((fgets(buf,sizeof(buf),data))!=0) {
- switch(htype(buf)) {
- case FROM:
- case MSGID:
- case RECEIVED:
- fgets(buf,sizeof(buf),data); /*eat the id*/
- continue;
- }
- fputs(buf,f);
- }
- rewind(f);
- mp->id = strdup(mp->buf);
- xfer_article2(f,mp);
- /*
- log(-1,"NNGT: transfer: Msg %s",mp->id);
- */
- quit:
- fclose(f);
- free(mp);
- return 0;
- }
-
- /* ---------------------------- Servercmd --------------------------- */
-
- /* Start up NNTP receiver service */
- int
- nntp1(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct sockaddr_in lsocket;
- int s;
-
- if(Snntp != -1)
- return -1;
- if(check_system() == -1)
- return -1;
-
- psignal(Curproc,0); /* Don't keep the parser waiting */
- chname(Curproc,"NNTP listener");
-
- lsocket.sin_family = AF_INET;
- lsocket.sin_addr.s_addr = INADDR_ANY;
- lsocket.sin_port = (argc < 2) ? IPPORT_NNTP : atoi(argv[1]);
-
- Snntp = socket(AF_INET,SOCK_STREAM,0);
- bind(Snntp,(char *)&lsocket,sizeof(lsocket));
- listen(Snntp,1);
-
- for(;;){
- if((s = accept(Snntp,NULLCHAR,(int *)NULL)) == -1)
- break; /* Service is shutting down */
-
- /* Low mem check now done in tcpin.c - WG7J */
- sockmode(s,SOCK_ASCII);
- /* Spawn a server */
- newproc("NNTP server",2048,nntpserv,s,NULL,NULL,0);
- }
- return 0;
- }
-
- /* Shutdown NNTP service (existing connections are allowed to finish) */
- int
- nntp0(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- close_s(Snntp);
- Snntp = -1;
- return 0;
- }
-
- /* ---------------------------- Subcmds --------------------------- */
-
- /* lists active newsgroups
- * returncode: -1 if error; 0 success */
- static int
- donnactive(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- FILE *fp;
- char line[80], *cp;
-
- if((fp = open_file(Active,READ_TEXT,0,1)) == NULLFILE)
- return -1;
-
- tputs("Msg# next mod newsgroup\n");
-
- for(;;) {
- if (fgets(line,sizeof(line),fp) == NULL)
- break;
- if((cp = strchr(line,' ')) == NULLCHAR)
- break;
- *cp = '\0';
- rip(++cp);
- tprintf("%s %s\n",cp,line);
- }
- fclose(fp);
- return 0;
- }
-
- /* add nntp servers to list */
- static int
- donnadds(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct Servers *np;
-
- for(np = Nntpserver; np != NULLSERVER; np = np->next)
- if(stricmp(np->name,argv[1]) == 0)
- break;
- if (np == NULLSERVER) {
- np = (struct Servers *)callocw(1,sizeof(struct Servers));
- if((np->dest = resolve(argv[1])) == 0) {
- tprintf(Badhost,argv[1]);
- free((char *)np);
- return -1;
- }
- np->name = strdup(argv[1]);
- np->next = Nntpserver;
- Nntpserver = np;
- np->newsgroups = NULLCHAR;
- np->lowtime = np->hightime = -1;
- np->nntpt.func = poll; /* what to call on timeout */
- np->nntpt.arg = (void *)np;
- }
- if (argc > 3) {
- int i;
- if (np->newsgroups == NULLCHAR) {
- np->newsgroups = callocw(1,LineLen);
- *np->newsgroups = '\0';
- }
- for (i = 3; i < argc; ++i) {
- if (isdigit(*argv[i])) {
- int lh, ll, hh, hl;
- sscanf(argv[i], "%d:%d-%d:%d", &lh, &ll, &hh, &hl);
- np->lowtime = lh * 100 + ll;
- np->hightime = hh * 100 + hl;
- } else if ((strlen(np->newsgroups)+strlen(argv[i])+2) >= LineLen)
- tprintf("To many groups, '%s' ignored\n", argv[i]);
- else { /* it's a group, and it fits... add it to list */
- if (*np->newsgroups != '\0')
- strcat(np->newsgroups, ",");
- strcat(np->newsgroups, argv[i]);
- }
- }
- if (*np->newsgroups == '\0') { /* No groups specified? */
- free(np->newsgroups);
- np->newsgroups = NULLCHAR;
- }
- }
- /* set timer duration */
- set_timer(&np->nntpt,atol(argv[2])*1000L);
- start_timer(&np->nntpt); /* and fire it up */
- return 0;
- }
-
- /* drops nntp servers from list */
- static int
- donndrops(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct Servers *np, *npprev = NULLSERVER;
-
- for(np = Nntpserver; np != NULLSERVER; npprev = np, np = np->next)
- if(stricmp(np->name,argv[1]) == 0) {
- stop_timer(&np->nntpt);
- free(np->name);
- if (np->newsgroups)
- free(np->newsgroups);
- if(npprev != NULLSERVER)
- npprev->next = np->next;
- else
- Nntpserver = np->next;
- free((char *)np);
- return 0;
- }
- tputs("No such server enabled.\n");
- return -1;
- }
-
- /* copies a news from given newsgroup to the mailbox */
- static int
- donndump(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- FILE *t, *f, *o;
- char path[LineLen], line[LineLen], *cp, newsname[25], *cp1;
- struct ffblk blk;
-
- if (!Filecheck)
- if(check_system())
- return -1;
-
- if ((f = open_file(Pointer,READ_TEXT,0,1)) == NULLFILE)
- return 0;
-
- path[0] = '\0';
- line[0] = '\0';
-
- for(;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- if (!strncmp(line,argv[1],strlen(argv[1]))) {
- cp = strchr(line,' ') + 1;
- strcpy(path,cp);
- break;
- }
- }
- fclose(f);
-
- if (path[0] == '\0') {
- tprintf("No newsgroup %s\n",argv[1]);
- goto error;
- }
-
- rip2(path);
- cp = strrchr(path,'/');
- cp1 = &newsname[0];
-
- while(*cp)
- *(cp1++) = *(cp++);
- *cp1 = '\0';
-
- strcpy(line,path);
- strcat(line,"/*.*");
- if(findfirst(line,&blk,0)) {
- tputs("No news in newsgroup\n");
- goto error;
- }
- if(argc > 2)
- sprintf(newsname,"/%s",argv[2]);
-
- sprintf(line,"%s%s.txt",Mailspool,newsname);
- if ((o = open_file(line,"a+",0,1)) == NULLFILE)
- goto error;
- if(!(mlock(Mailspool,newsname))) {
- tprintf("Newsgroup dump to %s\n",line);
- for (;;) {
- if((t = temp_file(0,1)) == NULLFILE) {
- fclose(o);
- goto error;
- }
- sprintf(line,"%s/%s",path,blk.ff_name);
- /* Open the article */
- if ((f = open_file(line,READ_TEXT,0,1)) == NULLFILE) {
- fclose(t);
- fclose(o);
- goto error;
- }
- pwait(NULL);
- tputc('.'); /* One dot/article processed */
- tflush();
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- fputs(line,t);
- if (!strnicmp(line,Hdrs[FROM],6)) {
- cp = strchr(line,' ')+1;
- fprintf(o,"From %s",cp);
- }
- }
- rewind(t);
- for(;;) {
- if (fgets(line,LineLen,t) == NULL)
- break;
- fputs(line,o);
- }
- fputc('\n',o);
- fclose(t);
- fclose(f);
- if (findnext(&blk))
- break;
- }
- rmlock(Mailspool,newsname);
- } else
- tputs("Mailfile is busy, try later");
- fclose(o);
- tputs("\n");
-
- error:
- return 0;
- }
-
- static int
- donnkick(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct Servers *np;
-
- for(np = Nntpserver; np != NULLSERVER; np = np->next)
- if(!stricmp(np->name,argv[1])) {
- /* If the timer is not running, the timeout function has
- * already been called and we don't want to call it again.
- */
- if(run_timer(&np->nntpt) || dur_timer(&np->nntpt) == 0) {
- stop_timer(&np->nntpt);
- poll((void *)np);
- }
- return 0;
- }
- tputs("No server enabled\n");
- return 0;
- }
-
- /* list nntp servers */
- static int
- donnlists(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct Servers *np;
- char tbuf[80];
-
- for(np = Nntpserver; np != NULLSERVER; np = np->next) {
- if (np->lowtime != -1 && np->hightime != -1)
- sprintf(tbuf, " -- %02d:%02d-%02d:%02d",
- np->lowtime/100, np->lowtime%100,
- np->hightime/100, np->hightime%100);
- else
- tbuf[0] = '\0';
- tprintf("%-32s (%lu/%lu%s)\n Groups: %s\n", np->name,
- read_timer(&np->nntpt) /1000L,
- dur_timer(&np->nntpt) /1000L,
- tbuf, np->newsgroups ? np->newsgroups : "");
- }
- return 0;
- }
-
- /* manually entering new news
- * returncode: -1 if error; 0 success */
- static int
- donnpost(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct session *sp;
- struct nntpsv *mp;
- char buf[LineLen];
- int id;
- FILE *f, *idf, *ufp;
- long currtime;
-
- if (!Filecheck)
- if(check_system())
- return -1;
-
- if((sp = newsession("Post",0,1)) == NULLSESSION)
- return -1;
-
- mp = (struct nntpsv *)callocw(1,sizeof(struct nntpsv));
-
- for (;;) {
- if ((f = temp_file(0,1)) == NULLFILE)
- goto done;
-
- sprintf(buf,"%s/sequence.seq",Mailqdir);
- if ((idf = open_file(buf,"r+",0,1)) == NULLFILE) {
- tprintf("Please create %s dir ...\n",Mailqdir);
- fclose(f);
- goto done;
- }
-
- id = atoi(fgets(buf,LineLen,idf));
- rewind(idf);
- fprintf(idf,"%d",id+2);
- fclose(idf);
-
- if (Post->user == NULLCHAR) {
- tputs("User name? ");
- recvline(sp->input,buf,LineLen);
- rip2(buf);
- Post->user = strdup(buf);
- }
- fprintf(f,"%s%s\n",Hdrs[PATH],Post->user);
- fprintf(f,"%s%s@%s",Hdrs[FROM],Post->user,Hostname);
- if (Post->fullname != NULLCHAR)
- fprintf(f," (%s )",Post->fullname);
- fputc('\n',f);
-
- tputs("Newsgroup? ");
- recvline(sp->input,buf,LineLen);
- rip2(buf);
- if (check_blank(buf))
- goto done;
- fprintf(f,"%s%s\n",Hdrs[NEWSGROUPS],buf);
-
- tputs("Subject? ");
- recvline(sp->input,buf,LineLen);
- fprintf(f,"%s%s",Hdrs[SUBJECT],buf);
- fprintf(f,"%s<%d@%s>\n",Hdrs[MSGID],id,Hostname);
- time(&currtime);
- fprintf(f,"Date: %s",ptime(&currtime));
- fprintf(f,"Sender: NNTP@%s\n",Hostname);
-
- if (Post->reply != NULLCHAR)
- fprintf(f,"%s%s\n",Hdrs[REPLYTO],Post->reply);
-
- if (Post->organ != NULLCHAR)
- fprintf(f,"Organization: %s\n",Post->organ);
-
- fputc('\n',f);
- tputs("Enter message - end with .\n");
-
- for (;;) {
- recvline(sp->input,buf,LineLen);
- if(strcmp(buf,".u\n") == 0
- || strcmp(buf,".r\n") == 0) {
- tputs("Filename? ");
- recvline(sp->input,buf,LineLen);
- rip2(buf);
- if((ufp = open_file(buf,READ_TEXT,0,1)) != NULLFILE) {
- while(fgets(buf,LineLen,ufp) != NULL)
- fputs(buf,f);
- fclose(ufp);
- }
- tputs("(continue)\n");
- }
- if(strcmp(buf,".\n") == 0
- || strcmpi(buf,"***END\n") == 0
- || strcmpi(buf,"/EX\n") == 0)
- break;
- fputs(buf,f);
- }
-
- if (Post->sig != NULLCHAR) {
- sprintf(buf,"%s",Post->sig);
- if ((idf = open_file(buf,READ_TEXT,0,1)) != NULLFILE ) {
- while(fgets(buf,LineLen,idf) != NULL)
- fputs(buf,f);
- fclose(idf);
- }
- }
-
- loop: tputs("\n[Send, Abort, Exit, List] ");
- recvline(sp->input,buf,LineLen);
- switch(tolower(buf[0])) {
- case 's':
- rewind(f);
- sprintf(mp->buf,"<%d@%s>",id,Hostname);
- mp->id = strdup(mp->buf);
- xfer_article2(f,mp);
- break;
- case 'l':
- rewind(f);
- for(;;) {
- if (fgets(buf,LineLen,f) == NULL)
- break;
- tputs(buf);
- }
- rewind(f);
- goto loop;
- case 'e':
- fclose(f);
- goto done;
- case 'a':
- break;
- default:
- goto loop;
- }
- fclose(f);
- tputs("Post another? ");
- recvline(sp->input,buf,LineLen);
- if (tolower(buf[0]) == 'n')
- goto done;
- }
-
- done:
- if(f != NULLFILE)
- fclose(f);
- keywait(NULLCHAR,1);
- free((char *) mp);
- freesession(sp);
- return 0;
- }
-
- static int
- donnquiet(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setintrc(&Nntpquiet,"NNTP quiet",argc,argv,0,2);
- }
-
- /* -------------------- Profile subcmds -------------------- */
-
- static int
- donnuser(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2 && Post->user != NULLCHAR)
- tprintf("%s\n",Post->user);
- else {
- free(Post->user);
- Post->user = strdup(argv[1]);
- }
- return 0;
- }
-
- static int
- donnsig(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2 && Post->sig != NULLCHAR)
- tprintf("%s\n",Post->sig);
- else {
- if(access(argv[1],0) == 0) {
- free(Post->sig);
- Post->sig = strdup(argv[1]);
- } else {
- tputs("No such signature file\n");
- return -1;
- }
- }
- return 0;
- }
-
- static int
- donnfull(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2 && Post->fullname != NULLCHAR)
- tprintf("%s\n",Post->fullname);
- else {
- free(Post->fullname);
- Post->fullname = strdup(argv[1]);
- }
- return 0;
- }
-
- static int
- donnhost(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2 && Host != NULLCHAR)
- tprintf("%s\n",Host);
- else {
- free(Host);
- Host = strdup(argv[1]);
- }
- return 0;
- }
-
- static int
- donnorgan(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2 && Post->organ != NULLCHAR)
- tprintf("%s\n",Post->organ);
- else {
- free(Post->organ);
- Post->organ = strdup(argv[1]);
- }
- return 0;
- }
-
- static int
- donnreply(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- if(argc < 2 && Post->reply != NULLCHAR)
- tprintf("%s\n",Post->reply);
- else {
- free(Post->reply);
- Post->reply = strdup(argv[1]);
- }
- return 0;
- }
-
- /* subcmd parser */
- static int
- donnprofile(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct cmds Prof[] = {
- "fullname", donnfull, 0, 0, NULLCHAR,
- "host", donnhost, 0, 0, NULLCHAR,
- "organ", donnorgan, 0, 0, NULLCHAR,
- "reply", donnreply, 0, 0, NULLCHAR,
- "sig", donnsig, 0, 0, NULLCHAR,
- "user", donnuser, 0, 0, NULLCHAR,
- NULLCHAR,
- };
- if(Post == NULLPOST) {
- Post = (struct post *)callocw(1,sizeof(struct post));
- Post->user = Post->reply = Post->sig = Post->organ = Post->fullname = NULLCHAR;
- }
- if (Host == NULLCHAR) {
- Host = strdup(Hostname);
- }
- return (argc == 10) ? 0 : (subcmd(Prof,argc,argv,p));
- }
-
- /* cmd parser */
- int
- donntp(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct cmds Nntp[] = {
- "active", donnactive, 0, 0, NULLCHAR,
- "add", donnadds, 0, 3, "nntp add <nntpserv> <interval> [<groups>]",
- "drop", donndrops, 0, 2, "nntp drop <nntpserv>",
- "dump", donndump, 0, 2, "nntp dump <newsgroup> [<mailbox>]",
- "kick", donnkick, 0, 2, "nntp kick <server>",
- "list", donnlists, 0, 0, NULLCHAR,
- "post", donnpost, 2024, 0, NULLCHAR,
- "profile", donnprofile, 0, 0, NULLCHAR,
- "quite", donnquiet, 0, 0, NULLCHAR,
- NULLCHAR,
- };
-
- return (subcmd(Nntp,argc,argv,p));
- }
-
- /* main file-opening routine
- * options: s = socketnumber, if given an error msg is printed to the socket
- * returncode: NULLFILE if error; filepointer success
- */
- FILE *
- open_file(name,mode,s,t)
- char *name;
- char *mode;
- int s;
- int t;
- {
- FILE *f;
- register char *cp;
-
- if(name == NULLCHAR || mode == NULLCHAR)
- return NULLFILE;
- #ifdef MSDOS
- while((cp = strchr(name,'\\')) != NULLCHAR)
- *cp = '/';
- #endif
- if((f = fopen(name,mode)) == NULLFILE) {
- if(s)
- usprintf(s,fatal,"",name);
- if(t)
- tprintf("Can't open %s: %s\n",name,strerror(errno));
- }
- return f;
- }
-
- /* main tempfile-opening routine
- * returncode: NULLFILE if error; filepointer success
- */
- FILE *
- temp_file(s,t)
- int s;
- int t;
- {
- FILE *f;
-
- if((f = tmpfile()) == NULLFILE) {
- if(s)
- usprintf(s,fatal,"TMP","");
- if(t) {
- tprintf("Can't open TMP: %s\n",strerror(errno));
- }
- }
- return f;
- }
-
- /* Subroutine for setting and displaying int variables (with range check) */
- int
- setintrc(var, label, argc, argv, minval, maxval)
- int16 *var;
- char *label;
- int argc;
- char *argv[];
- int minval;
- int16 maxval;
- {
- int tmp;
-
- if (argc < 2)
- tprintf("%s: %u\n", label, *var);
- else {
- tmp = atoi(argv[1]);
- if (isalpha(*argv[1]) || tmp < minval || tmp > maxval) {
- tprintf("%s must be %i..%i\n", label, minval, maxval);
- return 1;
- }
- *var = (int16)tmp;
- }
- return 0;
- }
- #endif /* NNTPS */
-
-